<?php
/**
 * Created by PhpStorm.
 * User: yzr
 * Date: 2/2/2021
 * Time: 20:37
 */
namespace mall\library\payex;

use think\Exception;

class PayexService
{
    private $config = [
        'email' => '',
        'secret'=> '',
        'url'   => '',
        'notifyUrl'    => '',
        'returnUrl' => '',
    ];

    //const API_SERVER = 'https://sandbox-payexapi.azurewebsites.net';
    const API_SERVER = 'https://api.payex.io';

    const API_URL_TOKEN = '/api/Auth/Token';
    const API_URL_PAYMENT = '/Payment/Details';

    /**
     * 用于设置api请求的参数
     * @var array
     */
    private $apiParams = [];

    private $token = null;

    /**
     * 初始化配置参数
     * PayexService constructor.
     * @param $config
     * @throws Exception
     */
    public function __construct(array $config = null)
    {
        $config = is_null($config)?[]:$config;
        $tmpConfig = config('pay.payex');
        $config = array_merge([
            'notifyUrl'    => '',
            'returnUrl' => '',
        ],is_array($tmpConfig)?$tmpConfig:[],$config);
        foreach($this->config as $key=>$value) {
            if(!array_key_exists($key,$config)) {
                throw new Exception(' Missing configuration parameter ' . $key);
            }
            $this->config[$key] = $config[$key];
        }
    }


    /**
     * 请求支付
     */
    public function doPayUrl()
    {

        $fields = ['token','key','collection_id','amount','customer_name','area_code','contact_number','email','address','postcode','city','state','country','reference_number','description','payment_type','tokenize','card_on_file',
            'return_url','callback_url','accept_url','reject_url','template','nonce'];
        $token = $this->getToken();
        $this->setApiParams(array_merge($this->apiParams,[
            'token' => $token,
            'key' => $token,
            'return_url'    => urlencode($this->config['returnUrl']),
            'callback_url'    => urlencode($this->config['notifyUrl']),
        ]));
        $data = [];
        foreach($fields as $key) {
            if(array_key_exists($key,$this->apiParams)) {
                $data[] = $key . '=' . $this->apiParams[$key];
            }
        }
        return static::API_SERVER . static::API_URL_PAYMENT . '?' . implode('&',$data);
    }


    /**
     * 验证签名
     * @param $txn_id
     * @param $signature
     */
    public function signatureValidate($signature,$txn_id)
    {
        return $signature == hash('sha512',$this->config['secret'] . '|' . $txn_id);
    }


    /**
     * 设置API的请求参数
     * @param $params
     */
    public function setApiParams($params)
    {
        $this->apiParams = $params;
    }




    /**
     * 请求第三方，并获取结果
     * @param $api
     * @param $method
     * @param $data
     * @param $headers
     * @return mixed
     * @throws \Exception
     */
    private function request($api,$method,$data,$headers,$setToken = true)
    {
        if($setToken) {
         //   $headers[] = $this->getToken();
        }
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, static::API_SERVER . $api);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

        if($method == 'POST') {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        if(!empty($headers)) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }
        $response = curl_exec($curl);
        $httpCode = curl_getinfo($curl,CURLINFO_HTTP_CODE);
        curl_close($curl);
        if($httpCode !== 200) {
            $this->throwErr('数据请求错误，请稍后再试');
        }
        return json_decode($response,true);
    }



    /**
     * 获取token
     * @return mixed
     * @throws \Exception
     */
    private function getToken()
    {
        $headers = [
            'Authorization: Basic ' . base64_encode($this->config['email'] . ':' .$this->config['secret']),
            'Content-Type:application/json',
        ];
        $response = $this->request(static::API_URL_TOKEN,'POST',[],$headers,false);
        if(!array_key_exists('token',$response)) {
            $this->throwErr();
        }
        return $response['token'];
    }

    /**
     * 抛出错误提示
     * @param $msg
     * @throws \Exception
     */
    private function throwErr($msg = '请求第三方数据无效') {
        throw new \Exception($msg);
    }

}
